home *** CD-ROM | disk | FTP | other *** search
/ Oh!X 2000 Spring / Oh!X 2000 Spring Special CD-ROM (Japan) (Part 1).7z / Oh!X 2000 Spring Special CD-ROM (Japan) (Part 1).bin / F2JW / trans / sentence.cpp < prev    next >
C/C++ Source or Header  |  1999-08-22  |  37KB  |  1,495 lines

  1. //
  2. // フランス語 → 日本語 翻訳プログラム
  3. //
  4. // 文章構成 (主にセンテンスがらみ)
  5.  
  6. #include "stdafx.h"
  7.  
  8. #include    "f2j.h"
  9. #include    "score.h"
  10. #include    "myprot.h"
  11.  
  12. extern    BOOL        isChanged;
  13. extern    TOKEN        *lastToken;
  14. extern    TOKEN        *currentTree;
  15.  
  16. //
  17. // 比較形容詞を持つ文章 + <que> + <主語> + <動詞>
  18. //
  19. void
  20. CombineMoreThan(TOKEN *start)
  21. {
  22.     TOKEN    *p;
  23.     TOKEN    *lastOwner = NULL, *lastThan = NULL;
  24.     TOKEN    *compWord = NULL;
  25.  
  26.     for(p = start->next; p; p = p->next) {
  27.         TOKEN    *owner = IsWordOwner(p, FR_ATTRIB_COMPARE);
  28.         if(owner
  29.         && !SearchToken(FR_PART_CONJUNCTION_THAN, owner->child)) {
  30.             lastOwner = p;
  31.             lastThan = NULL;
  32.         } else if(IsObjectMatch(p, FR_PART_CONJUNCTION_THAN)) {
  33.             lastThan = p;
  34.         } else if(ToWaitCombineMoreThan(lastThan, p)) {
  35.             lastOwner = lastThan = NULL;
  36.         }
  37.     }
  38.     if(lastOwner == NULL
  39.     || lastThan == NULL
  40.     || lastThan->next == NULL)
  41.         return;
  42.  
  43.     compWord =IsWordOwner(lastOwner, FR_ATTRIB_COMPARE);
  44.     if(compWord == NULL)    return;
  45.  
  46.     if(lastThan->object1 == NULL
  47.     && IsObjectMatch(lastThan->next, (FR_PART)(FR_PART_NOUN_PERSONAL | FR_PART_NOUN_GENERAL | FR_PART_NOUN_DEMONSTRATIVE))) {
  48.         for(TOKEN *q = lastThan; q; q = q->next) {
  49.             q = SearchToken(FR_PART_VERB_ALL, q);
  50.             if(q == NULL)    break;
  51.             if((q->frPart & FR_PART_COMBINE) &&  q->object1 == NULL)
  52.                 continue;
  53.             break;
  54.         }
  55.         if(q == NULL) {
  56.             TOKEN *sub = lastThan->next;
  57.             DisconnectTOKEN(start, sub);
  58.             lastThan->object1 = sub;
  59.         }
  60.     }
  61.     else if(IsObjectMatch(lastThan->next, FR_PART_ADVERB_ALL)) {
  62.         TOKEN *adv = lastThan->next;
  63.         DisconnectTOKEN(start, adv);
  64.         AddChildTOKEN(lastThan, adv);
  65.     }
  66.     // Marie est aussi intelligent que jolie.
  67.     else if(IsObjectMatch(lastThan->next, FR_PART_ADJECTIVE_ALL)
  68.     && lastThan->next->next == NULL) {
  69.         TOKEN *adj = lastThan->next;
  70.         DisconnectTOKEN(start, adj);
  71.         AddChildTOKEN(lastThan, adj);
  72.     }
  73.     else if(lastThan->object1 == NULL
  74.     && IsObjectMatch(lastThan->next, FR_PART_SENTENCE_ALL)
  75.     && lastThan->next->next == NULL) {
  76.         TOKEN *sentence = lastThan->next;
  77.         DisconnectTOKEN(start, sentence);
  78.         lastThan->object1 = sentence;
  79.     }
  80.     else
  81.         return;
  82.  
  83.     DisconnectTOKEN(start, lastThan);
  84.     AddChildTOKEN(compWord, lastThan);
  85.     compWord->scoreCombine += SCORE_MORE_THAN;
  86. }
  87.  
  88. //
  89. //
  90. //
  91. BOOL
  92. ToWaitCombineMoreThan(TOKEN *than, TOKEN *p)
  93. {
  94.     // 検討する意味がない
  95.     if(than == NULL)
  96.         return(TRUE);
  97.  
  98.     // 直後の文章は通す eg) than S+V
  99.     if(than->next != p
  100.     && p->frPart == FR_PART_SENTENCE_NORMAL)
  101.         return(TRUE);
  102.  
  103.     return(FALSE);
  104. }
  105.  
  106. //
  107. // 比較級・最上級の単語を持っているか
  108. //
  109. TOKEN
  110. *IsWordOwner(TOKEN *p, FR_ATTRIB frAttrib)
  111. {
  112.     TOKEN    *q;
  113.     TOKEN    *ret;
  114.  
  115.     if(p == NULL)    return(NULL);
  116.  
  117.     if(p->frAttrib & frAttrib)    return(p);
  118.  
  119.     for(q = p->child; q; q = q->next) {
  120.         ret = IsWordOwner(q, frAttrib);
  121.         if(ret != NULL)    return(ret);
  122.     }
  123.     for(q = p->object1; q; q = q->next) {
  124.         ret = IsWordOwner(p->object1, frAttrib);
  125.         if(ret != NULL)    return(ret);
  126.     }
  127.     for(q = p->object2; q; q = q->next) {
  128.         ret = IsWordOwner(p->object2, frAttrib);
  129.         if(ret != NULL)    return(ret);
  130.     }
  131.  
  132.     return(NULL);
  133. }
  134.  
  135. //
  136. // 指定されたFR_PARTを持っているか
  137. //
  138. TOKEN
  139. *IsWordOwner(TOKEN *p, FR_PART frPart)
  140. {
  141.     TOKEN    *q;
  142.     TOKEN    *ret;
  143.  
  144.     if(p == NULL)    return(NULL);
  145.  
  146.     if(IsObjectMatch(p, frPart))    return(p);
  147.  
  148.     for(q = p->child; q; q = q->next) {
  149.         ret = IsWordOwner(q, frPart);
  150.         if(ret != NULL)    return(ret);
  151.     }
  152.     for(q = p->object1; q; q = q->next) {
  153.         ret = IsWordOwner(p->object1, frPart);
  154.         if(ret != NULL)    return(ret);
  155.     }
  156.     for(q = p->object2; q; q = q->next) {
  157.         ret = IsWordOwner(p->object2, frPart);
  158.         if(ret != NULL)    return(ret);
  159.     }
  160.  
  161.     return(NULL);
  162. }
  163.  
  164. //
  165. // 序数を持っているか
  166. //
  167. TOKEN
  168. *IsNumericOrderOwner(TOKEN *p)
  169. {
  170.     TOKEN    *q;
  171.     TOKEN    *ret;
  172.  
  173.     if(p == NULL)    return(NULL);
  174.  
  175.     if(p->frPart == FR_PART_NUMETRIC_ORDER)    return(p);
  176.  
  177.     for(q = p->child; q; q = q->next) {
  178.         ret = IsNumericOrderOwner(q);
  179.         if(ret != NULL)    return(ret);
  180.     }
  181.     for(q = p->object1; q; q = q->next) {
  182.         ret = IsNumericOrderOwner(p->object1);
  183.         if(ret != NULL)    return(ret);
  184.     }
  185.     for(q = p->object2; q; q = q->next) {
  186.         ret = IsNumericOrderOwner(p->object2);
  187.         if(ret != NULL)    return(ret);
  188.     }
  189.  
  190.     return(NULL);
  191. }
  192.  
  193. //
  194. // 最上級形容詞を持つ文章 + <de> + <名詞>
  195. //
  196. void
  197. CombineMostAmong(TOKEN *start)
  198. {
  199.     TOKEN    *p = start;
  200.     TOKEN    *lastSentence = NULL;
  201.     TOKEN    *compWord = NULL;
  202.  
  203.     while(p) {
  204.         if(p->frPart == FR_PART_SENTENCE_NORMAL)
  205.             lastSentence = p;
  206.         p = p->next;
  207.     }
  208.     if(lastSentence == NULL)    return;
  209.  
  210.     compWord =IsWordOwner(lastSentence, FR_ATTRIB_TOP);
  211.     if(compWord == NULL) {
  212.         // il est le deuxi}me du monde. 世界中で2番目の
  213.         compWord = IsNumericOrderOwner(lastSentence);
  214.     }
  215.  
  216.     if(compWord == NULL
  217.     // すでに、<de>(~の中で)を持っている。
  218.     || SearchToken(FR_PART_PREPOSIT_DE, compWord->child) != NULL)
  219.         return;
  220.  
  221.     TOKEN    *next = lastSentence->next;
  222.  
  223.     if(next
  224.     && IsObjectMatch(next, FR_PART_PREPOSIT_DE)) {
  225.         ConvertSpecialWord(next, FR_PART_PREPOSIT_DE);
  226.         if(SelectJpPreposition2(compWord, next)) {
  227.             DisconnectTOKEN(start, next);
  228.             AddChildTOKEN(compWord, next);
  229.             compWord->scoreCombine += SCORE_MOST_AMONG;
  230.         }
  231.     }
  232. }
  233.  
  234. TOKEN
  235. *GetMostRightToken(TOKEN *p, FR_PART frPart)
  236. {
  237.     if((p->frPart & FR_PART_COMBINE)
  238.     &&  p->object2
  239.     &&  IsObjectMatch(p->frPart, frPart)) {
  240.         return(GetMostRightToken(p->object2, frPart));
  241.     }
  242.     return(p);
  243. }
  244.  
  245. //
  246. // 文章 + 副詞 → 文章
  247. //
  248. void
  249. CombineSentenceAdverb(TOKEN *start)
  250. {
  251.     TOKEN    *p = start;
  252.     TOKEN    *lastSentence = NULL;
  253.     TOKEN    *lastAdverb = NULL;
  254.  
  255.     while(p && p->next) {
  256.         if(IsObjectMatch(p->frPart, FR_PART_SENTENCE_ALL)
  257.         && (p->next->frPart & FR_PART_ADVERB)) {
  258.             lastSentence = p;    lastAdverb = p->next;
  259.         }
  260.         if((p->frPart & FR_PART_ADVERB)
  261.         && IsObjectMatch(p->next, FR_PART_SENTENCE_ALL)) {
  262.             lastAdverb = p;        lastSentence = p->next;
  263.         }
  264.         p = p->next;
  265.     }
  266.  
  267.     if(lastSentence == NULL)    return;
  268.  
  269.     if(lastSentence->frPart & FR_PART_COMBINE) {
  270.         lastSentence = GetMostRightToken(lastSentence, FR_PART_VERB_ALL);
  271.     }
  272.  
  273.     if(lastAdverb->next == lastSentence)
  274.         // 副詞、文章 の順
  275.         lastAdverb->jpEmphasis |= JP_EMPHASIS_COMMA;
  276.  
  277.     AttachAdverb(start, lastSentence, lastAdverb);
  278.     // 副詞と主語を入れ替える場合もある eg) Hier c'{tait dimanche.
  279.     ProcessJpHint(lastSentence->subject, lastSentence);
  280. }
  281.  
  282. CMP_TOKEN    pat_SentencePersonal[] = {    // je le sais, moi.
  283.     CMP_TOKEN( FR_PART_SENTENCE_NORMAL,JP_PROP_NONE,    NULL),
  284.     CMP_TOKEN( FR_PART_SPECIAL_COMMA,    JP_PROP_NONE,    NULL),
  285.     CMP_TOKEN( FR_PART_NOUN_PERSONAL,    JP_PROP_NONE,    IsNotTokenCombine),
  286.     CMP_TOKEN( FR_PART_NONE)
  287. };
  288.  
  289. CMP_TOKEN    pat_PersonalSentence[] = {        // moi, je le sais.
  290.     CMP_TOKEN( FR_PART_NOUN_PERSONAL,    JP_PROP_NONE,    IsNotTokenCombine),
  291.     CMP_TOKEN( FR_PART_SPECIAL_COMMA,    JP_PROP_NONE,    NULL),
  292.     CMP_TOKEN( FR_PART_SENTENCE_NORMAL,JP_PROP_NONE,    NULL),
  293.     CMP_TOKEN( FR_PART_NONE)
  294. };
  295.  
  296. //
  297. // 人称名詞を用いた強調形
  298. // eg) moi, je le sais.
  299. //       je le sais, moi.
  300. //
  301. void
  302. CombineSentencePersonal(TOKEN *start)
  303. {
  304.  
  305.     TOKEN    *p = start->next;
  306.     TOKEN    *sentence = NULL, *noun = NULL;
  307.     TOKEN    *emphasis = NULL;
  308.  
  309.     if(p == NULL)    return;
  310.  
  311.     if(IsPatternMatch(pat_SentencePersonal, p)) {
  312.         noun = SkipTokens(p, 2);
  313.         sentence = p;
  314.     } else if(IsPatternMatch(pat_PersonalSentence, p)) {
  315.         noun = p;
  316.         sentence = SkipTokens(p, 2);
  317.     } else
  318.         return;
  319.     
  320.     if(emphasis == NULL)
  321.             emphasis = SearchToBeEmphasis(sentence, noun);
  322.  
  323.     if(emphasis) {
  324.         // Moi aussi, je chante. -> 私<も>歌う
  325.         emphasis->jpEmphasis |= (noun->jpEmphasis | JP_EMPHASIS_GA);
  326.         emphasis->scoreCombine += SCORE_SENTENCE_EMPHASIS_NOUN;
  327.  
  328.         DisconnectTOKEN(start, SkipTokens(p, 1));    // カンマを取り除く
  329.         DisconnectTOKEN(start, noun);
  330.         SelectJpVerb2(sentence->subject, sentence);
  331.     }
  332. }
  333.  
  334.  
  335.  
  336. //
  337. // 文章の中から強調すべき部分を探す
  338. //
  339. TOKEN
  340. *SearchToBeEmphasis(TOKEN *p, TOKEN *key)
  341. {
  342.     TOKEN    *q;
  343.  
  344.     if((p->frPart & FR_PART_NOUN)
  345.     && IsAttribMatch(p, key))
  346.         return(p);
  347.  
  348.     if(p->subject) {
  349.         for(q = p->subject; q; q = q->next) {
  350.             TOKEN *r = SearchToBeEmphasis(q, key);
  351.             if(r)    return(r);
  352.         }
  353.     }
  354.     if(p->object1) {
  355.         for(q = p->object1; q; q = q->next) {
  356.             TOKEN *r = SearchToBeEmphasis(q, key);
  357.             if(r)    return(r);
  358.         }
  359.     }
  360.     if(p->object2) {
  361.         for(q = p->object2; q; q = q->next) {
  362.             TOKEN *r = SearchToBeEmphasis(q, key);
  363.             if(r)    return(r);
  364.         }
  365.     }
  366.     if(p->child) {
  367.         for(q = p->child; q; q = q->next) {
  368.             TOKEN *r = SearchToBeEmphasis(q, key);
  369.             if(r)    return(r);
  370.         }
  371.     }
  372.     return(NULL);
  373. }
  374.  
  375.  
  376. BOOL
  377. IsLastToken(TOKEN *p)
  378. {
  379.     if(p->next == NULL
  380.     || p->next->frPart == FR_PART_COMBINE_VERB)
  381.         return(TRUE);
  382.  
  383.     return(FALSE);
  384. }
  385.  
  386.  
  387. // Dans la voiture, il y a un stylo.
  388. CMP_TOKEN    pat_PrepositionSentence1[] = {
  389.     CMP_TOKEN( FR_PART_PREPOSIT_ALL,    JP_PROP_ALL,    NULL),
  390.     CMP_TOKEN( FR_PART_SPECIAL_COMMA,    JP_PROP_NONE,    NULL),
  391.     CMP_TOKEN( FR_PART_SENTENCE_NORMAL,JP_PROP_ALL,    IsLastToken),
  392.     CMP_TOKEN( FR_PART_NONE )
  393. };
  394.  
  395. // Dans la voiture il y a un stylo. (","がない)
  396. CMP_TOKEN    pat_PrepositionSentence2[] = {
  397.     CMP_TOKEN( FR_PART_PREPOSIT_ALL,    JP_PROP_ALL,    NULL),
  398.     CMP_TOKEN( FR_PART_SENTENCE_NORMAL,JP_PROP_ALL,    IsLastToken),
  399.     CMP_TOKEN( FR_PART_NONE)
  400. };
  401.  
  402. // Montez, jusqu'au moment. (","を外す)
  403. CMP_TOKEN    pat_Sentence_Preposition[] = {
  404.     CMP_TOKEN( FR_PART_SENTENCE_ALL,    JP_PROP_ALL,    NULL),
  405.     CMP_TOKEN( FR_PART_SPECIAL_COMMA,    JP_PROP_NONE,    NULL),
  406.     CMP_TOKEN( FR_PART_PREPOSIT_ALL,    JP_PROP_ALL,    IsLastToken),
  407.     CMP_TOKEN( FR_PART_NONE)
  408. };
  409.  
  410. BOOL
  411. IsTokenPPastVerb(TOKEN *p)
  412. {
  413.     if( p
  414.     &&  p->subject == NULL
  415.     && (p->frPart & FR_PART_VERB)
  416.     &&  p->which
  417.     &&  p->subject == NULL
  418.     && (p->frTense & FR_TENSE_P_PAST)
  419.     && (p->frPartChoice & FR_PART_INDEPENDENCE))
  420.         return(TRUE);
  421.     else
  422.         return(FALSE);
  423. }
  424.  
  425.  
  426. BOOL
  427. IsTokenPPresentVerb(TOKEN *p)
  428. {
  429.     if( p
  430.     && (p->frPart & FR_PART_VERB)
  431.     &&  p->which
  432. //    現在分詞は主語がある場合もある
  433. //    &&  p->subject == NULL
  434.     && (p->frTense & FR_TENSE_P_PRESENT)
  435.     && (p->frPartChoice & FR_PART_INDEPENDENCE))
  436.         return(TRUE);
  437.     else
  438.         return(FALSE);
  439. }
  440.  
  441. //
  442. // 前置詞 + "," + 文章 -> 文章
  443. //
  444. void
  445. CombinePrepositionSentence(TOKEN *start)
  446. {
  447.     TOKEN    *p = start->next;
  448.  
  449.     for(p = start; p; p = p->next) {
  450.         if(p->frPart & FR_PART_PREPOSIT) {    // IsObjectMatchでは、lui(FR_PART_NOUN_OBJECT_I)を前置詞と合致させてしまうため、
  451.             if(IsPatternMatch(pat_PrepositionSentence1, p)) {
  452.                 TOKEN    *comma = p->next, *sentence = p->next->next;
  453.                 DisconnectTOKEN(start, comma);    // ","を除く
  454.                 CombineSentencePreposition(start, sentence, p);
  455.             } else if(IsPatternMatch(pat_PrepositionSentence2, p)) {    // ","なし
  456.                 TOKEN    *sentence = p->next;
  457.                 CombineSentencePreposition(start, sentence, p);
  458.             }
  459.         } else {
  460.             if(IsPatternMatch(pat_Sentence_Preposition, p)) {
  461.                 TOKEN    *comma = p->next, *prep = p->next->next;
  462.                 if(prep->frPart & FR_PART_PREPOSIT) {    // IsObjectMatchでは、lui(FR_PART_NOUN_OBJECT_I)を前置詞と合致させてしまうため、
  463.                     DisconnectTOKEN(start, comma);    // ","を除く
  464.                     CombineSentencePreposition(start, p, prep);
  465.                 }
  466.             }
  467.         }
  468.     }
  469. }
  470.  
  471. //
  472. // 分詞構文
  473. //
  474. void
  475. CombinePPastSentence(TOKEN *start)
  476. {
  477.     TOKEN    *p = start->next;
  478.  
  479.     if(IsTokenPPastVerb(p) == FALSE)
  480.         return;
  481.  
  482.     TOKEN *verb = p;
  483.     do {
  484.         // 前置詞を飛ばす
  485.         // Couch{ <sur un canap{>, Jean lisait le journal.
  486.         p = p->next;
  487.     } while(p && (p->frPart & FR_PART_PREPOSIT));
  488.  
  489.     if(p
  490.     && ((  p->frPart == FR_PART_SPECIAL_COMMA
  491.         && p->next
  492.         && IsObjectMatch(p->next, FR_PART_SENTENCE_NORMAL))
  493.       || ( p->frPart == FR_PART_COMBINE_VERB
  494.         && p->object1 == NULL))) {
  495.         TOKEN *altP = CopyCurrentTree(verb, "PPastSentence", FR_PART_INDEPENDENCE);
  496.         verb->subject = PutNullNoun();
  497.         verb->frTense = FR_TENSE_PRESENT;    // 受け身ではない
  498.         verb->jpProp = (verb->jpProp * ~JP_PROP_PASSIVE);
  499.         verb->frPart = FR_PART_SENTENCE_PPAST;
  500.         isChanged = TRUE;
  501.     }
  502. }
  503.  
  504. BOOL
  505. IsTokenPPresentVerb_Last(TOKEN *p)
  506. {
  507.     if(!(p->frPart & FR_PART_COMBINE)
  508.     && IsTokenPPresentVerb(p)
  509.     && IsLastToken(p))
  510.         return(TRUE);
  511.  
  512.     return(FALSE);
  513. }
  514.  
  515. CMP_TOKEN    pat_SentencePPresent[] = {
  516.     CMP_TOKEN ( FR_PART_SENTENCE_NORMAL,    JP_PROP_NONE,    NULL    ),
  517.     CMP_TOKEN ( FR_PART_SPECIAL_COMMA,        JP_PROP_NONE,    NULL    ),
  518.     CMP_TOKEN ( FR_PART_VERB_ALL,            JP_PROP_NONE,    IsTokenPPresentVerb_Last ),
  519.     CMP_TOKEN ( FR_PART_NONE)
  520. };
  521.  
  522. //
  523. // 現在分詞構文
  524. //
  525. void
  526. CombinePPresentSentence(TOKEN *start)
  527. {
  528.     TOKEN    *p;
  529.  
  530.     for(p = start; p; p = p->next) {
  531.         if(IsPatternMatch(pat_SentencePPresent, p)) {
  532.             CombineSentencePPresent(start, p, p->next->next);
  533.             DisconnectTOKEN(start, p->next);    // Commaをとる
  534.             return;
  535.         }
  536.     }
  537.  
  538.     p = start->next;
  539.     if(IsTokenPPresentVerb(p) == FALSE)
  540.         return;
  541.  
  542.     TOKEN *verb = p;
  543.     do {
  544.         // 前置詞を飛ばす
  545.         // Couch{ <sur un canap{>, Jean lisait le journal.
  546.         p = p->next;
  547.     } while(p && (p->frPart & FR_PART_PREPOSIT));
  548.  
  549.     if(p
  550.     && p->frPart == FR_PART_SPECIAL_COMMA
  551.     && p->next
  552.     && IsObjectMatch(p->next, FR_PART_SENTENCE_NORMAL)) {
  553.         CombineSentencePPresent(start, p->next, verb);
  554.         DisconnectTOKEN(start, p);
  555.     } else if(p
  556.         && IsObjectMatch(p, FR_PART_COMBINE_VERB, JP_PROP_NONE, HasNoObjects, ",")) {
  557.         CombineSentencePPresent(start, p, verb);
  558.     }
  559. }
  560.  
  561. void
  562. CombineSentencePPresent(TOKEN *start, TOKEN *sentence, TOKEN *present)
  563. {
  564. //    TOKEN *altP = CopyCurrentTree(sentence, "PPresentSentence", FR_PART_INDEPENDENCE);
  565.  
  566.     if(present->subject == NULL) {
  567.         present->subject = sentence->subject;
  568.         present->synSubject = FALSE;
  569.     }
  570.     present->frPart = FR_PART_SENTENCE_PPRESENT;
  571.     present->jpEmphasis |= JP_EMPHASIS_COMMA;
  572.  
  573.     DisconnectTOKEN(start, present);
  574.     AddChildTOKEN(sentence, present);
  575.  
  576.     sentence->scoreCombine += SCORE_SENTENCE_PPRESENT;
  577. }
  578.  
  579. void
  580. CombineSentencePreposition(TOKEN *start, TOKEN *sentence, TOKEN *preposition)
  581. {
  582.     // 文章に掛ける
  583.     if(SelectJpPreposition2(sentence, preposition)) {
  584.         DisconnectTOKEN(start, preposition);
  585.         AddChildTOKEN(sentence, preposition);
  586.         preposition->jpEmphasis |= JP_EMPHASIS_COMMA;
  587.     }
  588. }
  589.  
  590. //
  591. // 過去分詞を用いた分詞構文
  592. //
  593. void
  594. CombineSentenceParticiple(TOKEN *start, TOKEN *sentence, TOKEN *verb)
  595. {
  596.     TOKEN    *subject = sentence->object1;
  597.  
  598.     // 文章が主語を持っていないとき
  599.     if(subject == NULL)    subject = sentence;
  600.  
  601.     // まず、文章に掛けてみる
  602.     SelectJpVerb2(subject, verb);
  603.     if(isChanged) {
  604.         DisconnectTOKEN(start, verb);
  605.         AddChildTOKEN(sentence, verb);
  606.         if(verb->frTense & FR_TENSE_P_PAST)
  607.             verb->frPart = FR_PART_SENTENCE_PPAST;
  608.         if(verb->frTense & FR_TENSE_P_PRESENT)
  609.             verb->frPart = FR_PART_SENTENCE_PPRESENT;
  610.     }
  611. }
  612.  
  613.  
  614. void
  615. SucceedSentences(TOKEN *sent, TOKEN *conj)
  616. {
  617.     sent->frPart = conj->frPart;
  618.     sent->what     = conj->what;
  619.     sent->which     = conj->which;
  620.     if(conj->child)
  621.         AddChildTOKEN(sent, conj->child);
  622. }
  623.  
  624. //
  625. // 名詞 + 現在分詞の文章
  626. //
  627. void
  628. ChangeParticipleToSentence(TOKEN *start)
  629. {
  630.     TOKEN    *p = start;
  631.     TOKEN    *verb = NULL;
  632.     TOKEN    *subject = NULL;
  633.  
  634.     while(p) {
  635.         if(p->frPart & FR_PART_NOUN)    subject = p;
  636.         if(p->frPart & FR_PART_VERB)    verb = p;
  637.         p = p->next;
  638.     }
  639.  
  640.     if(CanBeSubject(subject) == FALSE)    return;
  641.     if(verb != NULL)    return;
  642.  
  643.     verb = SearchToken(FR_PART_VERB_GENERAL, subject->child);
  644.     if(verb
  645.     && verb->frTense == FR_TENSE_P_PRESENT) {
  646.         DisconnectChildToken(subject, verb);
  647.         InsertTOKEN(subject, verb);
  648.         CombineSubjectVerb(start, subject, verb);
  649.     }
  650. }
  651.  
  652.  
  653. BOOL
  654. IsFirstToken(TOKEN *p)
  655. {
  656.     if(currentTree->next == p)    return(TRUE);
  657.     return(FALSE);
  658. }
  659.  
  660. BOOL
  661. HaveObject12(TOKEN *p)
  662. {
  663.     if(p->object1 && p->object2)    return(TRUE);
  664.     else            return(FALSE);
  665. }
  666.  
  667. BOOL
  668. HaveObject2(TOKEN *p)
  669. {
  670.     if(p->object2)    return(TRUE);
  671.     else            return(FALSE);
  672. }
  673.  
  674. void
  675. CombineSentenceEt(TOKEN *start)
  676. {
  677.     TOKEN    *p = start;
  678.  
  679.     // これは、文頭から、まとめ始まる。
  680.     for(p = start; p && p->next; p = p->next) {
  681.         TOKEN    *comma = NULL, *next = p->next;
  682.  
  683.         if(!IsObjectMatch(p, (FR_PART)(FR_PART_SENTENCE_ALL | FR_PART_INDEPENDENCE_ALL))
  684.         || (p->frTense & FR_TENSE_P_PRESENT)
  685.         || (p->frTense & FR_TENSE_P_PAST)) continue;
  686.  
  687.         // (Montez, grimpez), pers{v{rez. -> Montez, (grimpez, pers{v{rez).
  688.         if((p->frPart & FR_PART_COMBINE)
  689.         &&  p->object1 == NULL) continue;
  690.  
  691.         if(next->next
  692.         && next->frPart == FR_PART_SPECIAL_COMMA) {
  693.             comma = next;
  694.             next = next->next;
  695.         }
  696.         if((next->frPart & FR_PART_COMBINE)
  697.         && IsObjectMatch(next, FR_PART_SENTENCE_NORMAL)
  698.         && next->object1 == NULL
  699.         && next->object2 != NULL) {
  700.             if(comma) DisconnectTOKEN(start, comma);
  701.             CombineSentenceEt(start, p, next);
  702.         }
  703.     }
  704. }
  705.  
  706. void
  707. CombineSentenceEt(TOKEN *start, TOKEN *p, TOKEN *et)
  708. {
  709.     JP_COMBINE    *jpCombine = MatchJpCombine12(et, p, et->object2);
  710.     if(jpCombine == NULL) return;
  711.  
  712.     et->object1 = p;
  713.     DisconnectTOKEN(start, p);
  714.  
  715.     et->frPart = jpCombine->myFrPart;
  716.     if(jpCombine->myFrPart == FR_PART_COMBINE_VERB)
  717.         et->frPart = (FR_PART)(FR_PART_COMBINE | et->object2->frPart);
  718.  
  719.     et->which = jpCombine;
  720.     et->jpProp = et->object1->jpProp | et->object2->jpProp;
  721.     et->jpProp &= ~(JP_PROP_QUESTION | JP_PROP_NEGATIVE | JP_PROP_PASSIVE);
  722.     et->scoreCombine += SCORE_MAKE_SENTENCE;
  723.  
  724.     FixNoSubjectSentence(et, et->object1, et->object2);
  725.  
  726.     SelectJpCombine12(et, et->object1, et->object2);
  727.     if(IsObjectMatch(et->object1, FR_PART_SENTENCE_PPAST)) {
  728.         ImproveSubjectVerb(et->object2->subject, et->object1);
  729.     }
  730.     if(jpCombine->Exec)    (jpCombine->Exec)(et);
  731. }
  732.  
  733. void
  734. FixNoSubjectSentence(TOKEN *p, TOKEN *verb1, TOKEN *verb2)
  735. {
  736.     if(p == NULL
  737.     || verb1 == NULL
  738.     || verb2 == NULL)
  739.         return;
  740.  
  741.     if(verb2->frPart == FR_PART_COMBINE_VERB) {
  742.         FixNoSubjectSentence(p, verb1, verb2->object1);
  743.         FixNoSubjectSentence(p, verb1, verb2->object2);
  744.     }
  745.  
  746.     if(verb1->subject == NULL
  747.     || verb2->subject)
  748.         return;
  749.  
  750.     if(IsObjectMatch(verb2, FR_PART_SENTENCE_NO_SUBJECT)) {
  751.         // ils s'accordent et s'entendent bien.
  752.         // ils se entendent -> 再起代名詞として処理できるように
  753.         verb2->subject = verb1->subject;
  754.         ImproveSubjectVerb(verb1->subject, verb2);
  755.     }
  756. }
  757.  
  758. //
  759. // 前置詞無しの名詞修飾を、文章に加える
  760. // eg) J'ai vu M.Dupont la semaine derni}re.
  761. //
  762. CMP_TOKEN    pat_SentenceNounTime1[] = {
  763.     CMP_TOKEN ( FR_PART_NOUN_GENERAL,    JP_PROP_TIME,    HasArticleDefinitOrUnique ),
  764.     CMP_TOKEN ( FR_PART_SPECIAL_COMMA,    JP_PROP_NONE,    NULL        ),
  765.     CMP_TOKEN ( FR_PART_SENTENCE_NORMAL,JP_PROP_ALL,    IsLastToken    ),
  766.     CMP_TOKEN ( FR_PART_NONE)
  767. };
  768.  
  769. CMP_TOKEN    pat_SentenceNounTime2[] = {
  770.     CMP_TOKEN ( FR_PART_SENTENCE_NORMAL,JP_PROP_ALL,    NULL),
  771.     CMP_TOKEN ( FR_PART_NOUN_GENERAL,    JP_PROP_TIME,    HasArticleDefinitOrUnique ),
  772.     CMP_TOKEN ( FR_PART_NONE)
  773. };
  774.  
  775. CMP_TOKEN    pat_SentenceNounTime3[] = {
  776.     CMP_TOKEN ( FR_PART_SENTENCE_NORMAL,JP_PROP_ALL,    NULL),
  777.     CMP_TOKEN ( FR_PART_NOUN_ALL,        JP_PROP_TIME,    NULL, "tout"),
  778.     CMP_TOKEN ( FR_PART_NONE)
  779. };
  780. CMP_TOKEN    pat_SentenceNounTime4[] = {
  781.     CMP_TOKEN ( FR_PART_SENTENCE_NORMAL,JP_PROP_ALL,    NULL),
  782.     CMP_TOKEN ( FR_PART_NOUN_ALL,        JP_PROP_TIME,    NULL, "toute"),
  783.     CMP_TOKEN ( FR_PART_NONE)
  784. };
  785.  
  786.  
  787. void
  788. CombineSentenceNoun(TOKEN *start)
  789. {
  790.     CombineSentenceNounPPresent( start );
  791.     if(!isChanged)    CombineSentenceNounTime( start );
  792.     if(!isChanged)    CombineSentenceNounCe( start );
  793.     if(!isChanged)    CombineSentencePersonal( start );
  794.     if(!isChanged)    CombineSentenceNounMisc( start );
  795. }
  796.  
  797.  
  798. //
  799. // 名詞+現在分詞, S+V
  800. //
  801. BOOL
  802. HasPPresentVerb(TOKEN *p)
  803. {
  804.     if(!(p->frPartChoice & FR_PART_INDEPENDENCE))
  805.         return(FALSE);
  806.  
  807.     TOKEN *verb = SearchToken(FR_PART_SENTENCE_PPRESENT, p->child);
  808.     if(verb
  809.     && verb->subject == NULL)
  810.         return(TRUE);
  811.  
  812.     return(FALSE);
  813. }
  814.  
  815. CMP_TOKEN    pat_SentenceNounPPresent1[] = {
  816.     CMP_TOKEN ( FR_PART_NOUN_GENERAL,    JP_PROP_NONE,    HasPPresentVerb ),
  817.     CMP_TOKEN ( FR_PART_SPECIAL_COMMA,    JP_PROP_NONE,    NULL        ),
  818.     CMP_TOKEN ( FR_PART_SENTENCE_NORMAL,JP_PROP_ALL,    IsLastToken    ),
  819.     CMP_TOKEN ( FR_PART_NONE)
  820. };
  821. CMP_TOKEN    pat_SentenceNounPPresent2[] = {
  822.     CMP_TOKEN ( FR_PART_NOUN_GENERAL,    JP_PROP_NONE,    HasPPresentVerb ),
  823.     CMP_TOKEN ( FR_PART_COMBINE_VERB,    JP_PROP_NONE,    HasNoObjects    ),
  824.     CMP_TOKEN ( FR_PART_SENTENCE_NORMAL,JP_PROP_ALL,    IsLastToken    ),
  825.     CMP_TOKEN ( FR_PART_NONE)
  826. };
  827.  
  828. void
  829. CombineSentenceNounPPresent(TOKEN *start)
  830. {
  831.     TOKEN    *p = start->next;
  832.     TOKEN    *noun     = NULL;
  833.  
  834.     if(IsPatternMatch(pat_SentenceNounPPresent1, p)
  835.     || IsPatternMatch(pat_SentenceNounPPresent2, p)) {
  836.         noun = p;
  837.     } else 
  838.         return;
  839.  
  840.     // (time, S) + V -> time, (S+V)になるように
  841.     noun->scoreCombine += SCORE_SENTENCE_NOUN;
  842.  
  843.     TOKEN    *altP = CopyCurrentTree(noun, "PPresentSentence", FR_PART_INDEPENDENCE);
  844.  
  845.     TOKEN    *verb = SearchToken(FR_PART_SENTENCE_PPRESENT, noun->child);
  846.     DisconnectChildToken(noun, verb);
  847.     InsertTOKEN(noun, verb);
  848.     DisconnectTOKEN(start, noun);
  849.     verb->subject = noun;
  850.     verb->synSubject = TRUE;
  851.  
  852.     SelectJpVerb2(verb->subject, verb);
  853. }
  854.  
  855.  
  856. void
  857. CombineSentenceNounTime(TOKEN *start)
  858. {
  859.     TOKEN    *p = start->next;
  860.     TOKEN    *sentence = NULL;
  861.     TOKEN    *noun     = NULL;
  862.     TOKEN    *comma      = NULL;
  863.  
  864.     if(IsPatternMatch(pat_SentenceNounTime1, p)) {
  865.         noun = p;    comma = p->next;    sentence = p->next->next;
  866.         // (time, S) + V -> time, (S+V)になるように
  867.         noun->scoreCombine += SCORE_SENTENCE_NOUN;
  868.     } else {
  869.         while(p && p->next) {
  870.             if(IsPatternMatch(pat_SentenceNounTime2, p)
  871.             || IsPatternMatch(pat_SentenceNounTime3, p)
  872.             || IsPatternMatch(pat_SentenceNounTime4, p)) {
  873.                 sentence = p;    noun = p->next;
  874.             }
  875.             p = p->next;
  876.         }
  877.     }
  878.     if(sentence == NULL)    return;
  879.  
  880.     if(comma)    DisconnectTOKEN(start, comma);
  881.  
  882.     DisconnectTOKEN(start, noun);    // コンマを除く
  883.     AddChildTOKEN(sentence, noun);
  884.     noun->jpEmphasis |= JP_EMPHASIS_COMMA;
  885.     SelectJpVerb2(sentence->subject, sentence);
  886. }
  887.  
  888. CMP_TOKEN    pat_SentenceCe1[] = {
  889.     CMP_TOKEN ( FR_PART_SENTENCE_NORMAL,JP_PROP_ALL,    IsSubjectPersonalCe),
  890.     CMP_TOKEN ( FR_PART_SPECIAL_COMMA,    JP_PROP_NONE,    NULL),
  891.     CMP_TOKEN ( FR_PART_NOUN_GENERAL,    JP_PROP_ALL,    HasArticleDefinitOrUnique_End ),
  892.     CMP_TOKEN ( FR_PART_NONE)
  893. };
  894.  
  895. CMP_TOKEN    pat_SentenceCe2[] = {
  896.     CMP_TOKEN ( FR_PART_SENTENCE_NORMAL,JP_PROP_ALL,    IsSubjectPersonalCe),
  897.     CMP_TOKEN ( FR_PART_COMBINE_NOUN,    JP_PROP_NONE,    HasNoObjects),
  898.     CMP_TOKEN ( FR_PART_NOUN_GENERAL,    JP_PROP_ALL,    HasArticleDefinitOrUnique_End ),
  899.     CMP_TOKEN ( FR_PART_NONE)
  900. };
  901.  
  902. CMP_TOKEN    pat_CeSentence1[] = {
  903.     CMP_TOKEN ( FR_PART_NOUN_GENERAL,    JP_PROP_ALL,    HasArticleDefinitOrUnique),
  904.     CMP_TOKEN ( FR_PART_SPECIAL_COMMA,    JP_PROP_NONE,    NULL),
  905.     CMP_TOKEN ( FR_PART_SENTENCE_NORMAL,JP_PROP_ALL,    IsSubjectPersonalCe_End),
  906.     CMP_TOKEN ( FR_PART_NONE)
  907. };
  908.  
  909. CMP_TOKEN    pat_CeSentence2[] = {
  910.     CMP_TOKEN ( FR_PART_NOUN_GENERAL,    JP_PROP_ALL,    HasArticleDefinitOrUnique),
  911.     CMP_TOKEN ( FR_PART_COMBINE_NOUN,    JP_PROP_NONE,    HasNoObjects),
  912.     CMP_TOKEN ( FR_PART_SENTENCE_NORMAL,JP_PROP_ALL,    IsSubjectPersonalCe_End),
  913.     CMP_TOKEN ( FR_PART_NONE)
  914. };
  915.  
  916. // Ce que S+V, c'est A.
  917. CMP_TOKEN    pat_CeSentence3[] = {
  918.     CMP_TOKEN ( FR_PART_NOUN_SUBJECT,    "ce",    HasQue),
  919.     CMP_TOKEN ( FR_PART_SPECIAL_COMMA,    JP_PROP_NONE,    NULL),
  920.     CMP_TOKEN ( FR_PART_SENTENCE_NORMAL,JP_PROP_ALL,    IsSubjectPersonalCe_End),
  921.     CMP_TOKEN ( FR_PART_NONE)
  922. };
  923.  
  924. void
  925. CombineSentenceNounCe(TOKEN *start)
  926. {
  927.     TOKEN    *p = start->next;
  928.     TOKEN    *sentence = NULL;
  929.     TOKEN    *noun     = NULL;
  930.  
  931.     if(IsPatternMatch(pat_SentenceCe1, p)
  932.     || IsPatternMatch(pat_SentenceCe2, p)) {
  933.         sentence = p;    noun = p->next->next;
  934.         DisconnectTOKEN(start, p->next);    // コンマを除く
  935.     } else if(IsPatternMatch(pat_CeSentence1, p)
  936.            || IsPatternMatch(pat_CeSentence2, p)
  937.            || IsPatternMatch(pat_CeSentence3, p)) {
  938.         noun = p;        sentence = p->next->next;
  939.         DisconnectTOKEN(start, p->next);    // コンマを除く
  940.     } else
  941.         return;
  942.  
  943.     DisconnectTOKEN(start, noun);
  944.  
  945.     sentence->subject = noun;
  946.     noun->jpEmphasis |= JP_EMPHASIS_CE;
  947.     noun->scoreCombine += SCORE_SENTENCE_EMPHASIS_NOUN;
  948.  
  949.     SelectJpVerb2(sentence->subject, sentence);
  950. }
  951.  
  952.  
  953. CMP_TOKEN    pat_SentenceChacune[] = {
  954.     CMP_TOKEN ( FR_PART_SENTENCE_NORMAL,JP_PROP_ALL,    NULL),
  955.     CMP_TOKEN ( FR_PART_NOUN_ALL,     "chacune"),
  956.     CMP_TOKEN ( FR_PART_NONE)
  957. };
  958.  
  959. void
  960. CombineSentenceNounMisc(TOKEN *start)
  961. {
  962.     TOKEN    *p = start->next;
  963.     TOKEN    *sentence = NULL;
  964.     TOKEN    *noun     = NULL;
  965.  
  966.     for(p = start; p; p = p->next) {
  967.         if(IsPatternMatch(pat_SentenceChacune, p)) {
  968.             sentence = p;    noun = p->next;
  969.         }
  970.     }
  971.     if(sentence == NULL)    return;
  972.  
  973.     DisconnectTOKEN(start, noun);
  974.     AddChildTOKEN(sentence, noun);
  975.     SelectJpVerb2(sentence->subject, sentence);
  976. }
  977.  
  978.  
  979.  
  980. // Apres avoir parle, il est parti.
  981. CMP_TOKEN    pat_PrepositSentence1[] = {
  982.     CMP_TOKEN( FR_PART_PREPOSIT_ALL,    JP_PROP_NONE,    NULL),
  983.     CMP_TOKEN( FR_PART_SPECIAL_COMMA,    JP_PROP_NONE,    NULL),
  984.     CMP_TOKEN( FR_PART_SENTENCE_NORMAL,JP_PROP_ALL,    NULL),
  985.     CMP_TOKEN( FR_PART_NONE)
  986. };
  987.  
  988. // je crois qu'@ son arriv{, il sera accueilli.
  989. CMP_TOKEN    pat_PrepositSentence2[] = {
  990.     CMP_TOKEN( FR_PART_SENTENCE_QUE,    JP_PROP_NONE,    HasNoObjects),
  991.     CMP_TOKEN( FR_PART_PREPOSIT_ALL,    JP_PROP_NONE,    NULL),
  992.     CMP_TOKEN( FR_PART_SPECIAL_COMMA,    JP_PROP_NONE,    NULL),
  993.     CMP_TOKEN( FR_PART_SENTENCE_NORMAL,JP_PROP_ALL,    NULL),
  994.     CMP_TOKEN( FR_PART_NONE)
  995. };
  996.  
  997. void
  998. ChangeSentenceToAdverb(TOKEN *start)
  999. {
  1000.     TOKEN    *p = start->next;
  1001.     TOKEN    *sentence    = NULL;
  1002.     TOKEN    *adverb        = NULL;
  1003.     TOKEN    *disconnect    = NULL;
  1004.  
  1005.     if(IsPatternMatch(pat_PrepositSentence1, p)) {
  1006.         adverb = p;            sentence = p->next->next;
  1007.         disconnect = p->next;    // Disconnect ","
  1008.     }
  1009.  
  1010.     while(p && p->next) {
  1011.         if(IsPatternMatch(pat_PrepositSentence2, p)) {
  1012.             adverb = p->next;    sentence = SkipTokens(p, 3);
  1013.             disconnect = SkipTokens(p, 2);    // Disconnect ","
  1014.         }
  1015.         p = p->next;
  1016.     }
  1017.     if(sentence == NULL)    return;
  1018.  
  1019.     if(disconnect)    DisconnectTOKEN(start, disconnect);
  1020.  
  1021.     DisconnectTOKEN(start, adverb);
  1022.     AddChildTOKEN(sentence, adverb);
  1023. }
  1024.  
  1025. BOOL
  1026. HasRelatives(TOKEN *p)
  1027. {
  1028.     if(p) {
  1029.         if(p->child   && HasRelatives(p->child))    return(TRUE);
  1030.         if(p->object1 && HasRelatives(p->object1))    return(TRUE);
  1031.         if(p->object2 && HasRelatives(p->object2))    return(TRUE);
  1032.         if(SearchToken(FR_PART_RELATIVE_ALL, p))    return(TRUE);
  1033.     }
  1034.     return(FALSE);
  1035. }
  1036.  
  1037. BOOL
  1038. HasNoRelatives(TOKEN *p)
  1039. {
  1040.     if(p) {
  1041.         if(p->child   && HasRelatives(p->child))    return(FALSE);
  1042.         if(p->object1 && HasRelatives(p->object1))    return(FALSE);
  1043.         if(p->object2 && HasRelatives(p->object2))    return(FALSE);
  1044.     }
  1045.     return(TRUE);
  1046. }
  1047.  
  1048. // Il v{cut malheureux.
  1049. CMP_TOKEN    pat_SentenceAdjective[] = {
  1050.     CMP_TOKEN( FR_PART_SENTENCE_NORMAL,    JP_PROP_ALL,        HasNoRelatives),    // S1V2 <que> S2V2 ADJ -> ADJは、S2V2に掛るべき
  1051.     CMP_TOKEN( FR_PART_ADJECTIVE_GENERAL,    JP_PROP_CONDITION | JP_PROP_VOLUME,    IsLastToken),
  1052.     CMP_TOKEN( FR_PART_NONE)
  1053. };
  1054.  
  1055. void
  1056. CombineSentenceAdjective(TOKEN *start)
  1057. {
  1058.     TOKEN    *p = start->next;
  1059.     TOKEN    *sentence    = NULL;
  1060.     TOKEN    *adjective    = NULL;
  1061.  
  1062.     for(p = start->next; p; p= p->next) {
  1063.         if(IsPatternMatch(pat_SentenceAdjective, p)
  1064.         && !(p->next->frPart & FR_PART_INTERROGATIVE)) {
  1065.             sentence = p;        adjective = p->next;
  1066.         }
  1067.     }
  1068.     if(sentence == NULL)    return;
  1069.  
  1070.     AttachAdjective(start, sentence, adjective, FR_LOCATION_BEHIND);
  1071.  
  1072.     // il voyage <seul>.  seulは、副詞・形容詞どちらでもよいが、副詞 > 形容詞
  1073.     sentence->scoreCombine += SCORE_SENTENCE_ADJECTIVE;
  1074. }
  1075.  
  1076.  
  1077. //
  1078. // 独立文を処理
  1079. // que faire? 何をすべきか?
  1080. // 
  1081. void
  1082. ProcessIndependantSentence(TOKEN *start)
  1083. {
  1084.     TOKEN    *p;
  1085.     TOKEN    *lastInter = NULL;
  1086.  
  1087.     for(p = start; p; p = p->next) {
  1088.         if(p->frPart == FR_PART_INTERROGATIVE_UNCLEAR
  1089.         &&  p->which == NULL
  1090.         &&  p->next
  1091.         && (p->next->frPart & FR_PART_VERB)
  1092.         && (p->next->frTense & FR_TENSE_ORIGIN))
  1093.             lastInter = p;
  1094.     }
  1095.     if(lastInter == NULL)    return;
  1096.  
  1097.     TOKEN    *verb = lastInter->next;
  1098.     // Que faire? -> Que on faire? 後は、通常の疑問文と同じ
  1099.     verb->jpProp |= JP_PROP_QUESTION;
  1100. //    verb->frAttrib = FR_ATTRIB_IL;
  1101.     if(verb->object2) {    // 目的語2を放棄
  1102.         InsertTOKEN(verb, verb->object2);
  1103.         verb->object2 = NULL;
  1104.     }
  1105.     if(verb->object1) { // 目的語1を放棄
  1106.         InsertTOKEN(verb, verb->object1);
  1107.         verb->object1 = NULL;
  1108.     }
  1109.     verb->which = NULL;    // 仕切り直し
  1110.  
  1111.     TOKEN *subject = PutNullNoun();
  1112.     subject->frPart = FR_PART_NOUN_SUBJECT;
  1113.     subject->frAttrib = FR_ATTRIB_IL;
  1114.     subject->frTense = FR_TENSE_ORIGIN;        // 原形独立文の印
  1115.     InsertTOKEN(lastInter, subject);
  1116.  
  1117.     TOKEN *que = PutNullNoun();
  1118.     ChangeToSpecial(que, "que");
  1119.     que->frPartChoice = FR_PART_VERB;
  1120.     InsertTOKEN(lastInter, que);
  1121.     SwapToken(lastInter, que);
  1122.  
  1123. }
  1124.  
  1125.  
  1126. // il traduit, dans ses langue, sa solitude.
  1127. CMP_TOKEN    pat_InsertedPreposition[] = {
  1128.     CMP_TOKEN( FR_PART_SPECIAL_COMMA,    JP_PROP_NONE,    NULL),
  1129.     CMP_TOKEN( FR_PART_PREPOSIT_ALL,    JP_PROP_ALL,    CanVerbParent),
  1130.     CMP_TOKEN( FR_PART_SPECIAL_COMMA,    JP_PROP_NONE,    NULL),
  1131.     CMP_TOKEN( FR_PART_NONE)
  1132. };
  1133.  
  1134. void
  1135. ProcessInsertedPreposition(TOKEN *start)
  1136. {
  1137.     TOKEN    *p;
  1138.     TOKEN    *lastComma = NULL;
  1139.  
  1140.     for(p = start; p; p = p->next) {
  1141.         if(IsPatternMatch(pat_InsertedPreposition, p)) {
  1142.             lastComma = p;
  1143.         }
  1144.     }
  1145.     if(lastComma == NULL)    return;
  1146.  
  1147.     TOKEN    *inserted = SkipTokens(lastComma, 1);
  1148.  
  1149.     // 後続の文章にかからないように -> 接続詞をまたがない
  1150.     TOKEN    *lastToken = SearchToken(FR_PART_SENTENCE_ALL, inserted);
  1151.     if(lastToken == NULL)
  1152.         lastToken = GetLastTOKEN(start);
  1153.  
  1154.     DisconnectTOKEN(start, SkipTokens(lastComma, 2));
  1155.     DisconnectTOKEN(start, inserted);
  1156.     DisconnectTOKEN(start, lastComma);
  1157.  
  1158.     inserted->punctuation  = FR_PUNCT_COMMA;
  1159.     inserted->frPartParent = FR_PART_VERB;
  1160.     inserted->frPartChoice = FR_PART_NONE;
  1161.  
  1162.     InsertTOKEN(lastToken, inserted);
  1163. }
  1164.  
  1165.  
  1166. //
  1167. // 呼びかけなどの挿入句の処理
  1168. //
  1169. BOOL
  1170. CanBeInterjection(TOKEN *p)
  1171. {
  1172.     if((p->frPartChoice & FR_PART_INDEPENDENCE)
  1173.     && SearchToken(FR_PART_ADJECTIVE_EXCLAMINATION, p->child) == NULL)
  1174.         return(TRUE);
  1175.     else
  1176.         return(FALSE);
  1177. }
  1178.  
  1179. // je vous prie, Monsieur, de agger ...
  1180. CMP_TOKEN    pat_NounToInetjection[] = {
  1181.     CMP_TOKEN( FR_PART_SPECIAL_COMMA,    JP_PROP_NONE,    NULL),
  1182.     CMP_TOKEN( FR_PART_NOUN_GENERAL,    JP_PROP_HUMAN,    CanBeInterjection),
  1183.     CMP_TOKEN( FR_PART_SPECIAL_COMMA,    JP_PROP_NONE,    NULL),
  1184.     CMP_TOKEN( FR_PART_NONE)
  1185. };
  1186.  
  1187. void
  1188. ChangeNounToInterjection(TOKEN *start)
  1189. {
  1190.     TOKEN    *p;
  1191.     TOKEN    *lastComma = NULL;
  1192.  
  1193.     for(p = start; p; p = p->next) {
  1194.         if(IsPatternMatch(pat_NounToInetjection, p)) {
  1195.             lastComma = p;
  1196.         }
  1197.     }
  1198.     if(lastComma == NULL)    return;
  1199.  
  1200.     TOKEN    *parent = SearchToken(FR_PART_VERB, start);
  1201.     if(parent == NULL)
  1202.         parent = PreviousToken(start, lastComma);
  1203.     if(parent == NULL)
  1204.         return;
  1205.  
  1206.     TOKEN    *prev = PreviousToken(start, lastComma);
  1207.     prev->punctuation = FR_PUNCT_COMMA;
  1208.  
  1209.     TOKEN    *interjection = SkipTokens(lastComma, 1);
  1210.  
  1211.     DisconnectTOKEN(start, SkipTokens(lastComma, 2));
  1212.     DisconnectTOKEN(start, interjection);
  1213.     interjection->frPart = FR_PART_INDEPENDENCE_NOUN;
  1214. //    動詞と動詞の間に、感嘆詞が入る場合もあるので、","は取っておく
  1215. //    eg) Courte la t]te, <Sicambre>, bru~le ce que tu as ador{.
  1216. //    DisconnectTOKEN(start, lastComma);
  1217.     lastComma->frPartChoice = FR_PART_COMBINE_VERB;
  1218.  
  1219.     AddChildTOKEN(parent, interjection);
  1220. }
  1221.  
  1222. //
  1223. // 文章に、間投詞を足す。
  1224. //
  1225. void
  1226. CombineSentenceInterjection(TOKEN *start)
  1227. {
  1228.     if(start->next
  1229.     && start->next->next
  1230.     && start->next->next->frPart == FR_PART_SPECIAL_COMMA
  1231.     && start->next->next->next
  1232.     && IsObjectMatch(start->next->next->next, FR_PART_INDEPENDENCE_ALL)) {
  1233.         TOKEN    *interjection = SkipTokens(start, 3);
  1234.         TOKEN    *sentence = SkipTokens(start, 1);
  1235.         DisconnectTOKEN(start, SkipTokens(start, 2));
  1236.         DisconnectTOKEN(start, interjection);
  1237.         AddChildTOKEN(sentence, interjection);
  1238.     }
  1239. }
  1240.  
  1241.  
  1242. //
  1243. // 単純未来をもちいた文章 -> 命令形に
  1244. // Tu feras tes devoirs.
  1245. // あなたはあなたの義務をするだろう -> あなたの義務をしなさい
  1246. //
  1247. void
  1248. ChangeSimpleFutureToOrder(TOKEN *start)
  1249. {
  1250.     TOKEN    *sentence = start;
  1251.  
  1252.     if(sentence == NULL)    return;
  1253.  
  1254.     if( sentence->frPart == FR_PART_COMBINE_VERB
  1255.     && (sentence->object2)
  1256.     && (IsTokenFrench(sentence, ":") || (sentence->object2->frPart & FR_PART_COMBINE))) {
  1257.         // Vous aurez cong{ : vous irez visiter le mus{e.
  1258.         // あなたは休みなので、美術館に行きなさい。
  1259.         ChangeSimpleFutureToOrder(sentence->object2);
  1260.     }
  1261.  
  1262.     if( sentence
  1263.     &&  sentence->next == NULL
  1264.     && IsObjectMatch(sentence, FR_PART_SENTENCE_ALL)
  1265.     &&  sentence->subject
  1266.     && (sentence->subject->frPart & FR_PART_NOUN)
  1267.     && (sentence->subject->frAttrib & FR_ATTRIB_LEVEL2)
  1268.     && (sentence->frPart & FR_PART_VERB)
  1269.     && (sentence->frTense == FR_TENSE_FUTURE_SIMPLE)
  1270.     && !(sentence->jpProp & JP_PROP_QUESTION)) {
  1271.         sentence->subject->prtControl = PRT_CONTROL_DISABLE;
  1272.         sentence->frTense = FR_TENSE_ORDER;
  1273.     }
  1274. }
  1275.  
  1276. //
  1277. // 否定冠詞として処理した<de>のparentは、本当に否定されているか?
  1278. //
  1279. void
  1280. CheckNegativeArticle(TOKEN *start, BOOL isNegative)
  1281. {
  1282.     TOKEN    *p;
  1283. //    if(IsThereOtherSentence() == FALSE)    return;
  1284.  
  1285.     if(currentTree->prtControl == PRT_CONTROL_DISABLE)
  1286.         return;
  1287.  
  1288.     for(p = start; p; p = p->next) {
  1289.         if(IsObjectMatch(p, FR_PART_ARTICLE_NEGATIVE)
  1290.         && isNegative == FALSE) {
  1291.             currentTree->prtControl = PRT_CONTROL_DISABLE;
  1292.         }
  1293.         if(p->jpProp & JP_PROP_NEGATIVE)    isNegative = TRUE;
  1294.  
  1295.         if(p->child)    CheckNegativeArticle(p->child,     isNegative);
  1296.         if(p->object1)    CheckNegativeArticle(p->object1, isNegative);
  1297.         if(p->object2)    CheckNegativeArticle(p->object2, isNegative);
  1298.     }
  1299. }
  1300.  
  1301. //
  1302. // TOKEN->PREPOSITION中、使われていない前置詞をチェック
  1303. //
  1304. void
  1305. CheckUnusedPreposition(TOKEN *start)
  1306. {
  1307.     TOKEN    *p;
  1308.  
  1309.     if(currentTree->prtControl == PRT_CONTROL_DISABLE)
  1310.         return;
  1311.  
  1312.     for(p = start; p; p = p->next) {
  1313.         if(p->preposition) {
  1314.             currentTree->prtControl = PRT_CONTROL_DISABLE;
  1315.         }
  1316.  
  1317.         if(p->child)    CheckUnusedPreposition(p->child);
  1318.         if(p->object1)    CheckUnusedPreposition(p->object1);
  1319.         if(p->object2)    CheckUnusedPreposition(p->object2);
  1320.     }
  1321. }
  1322.  
  1323. void
  1324. CheckIllegalPreposition(TOKEN *start)
  1325. {
  1326.     TOKEN    *p;
  1327.     for(p = start; p && p->next; p = p->next) {
  1328.         TOKEN    *next = p->next;
  1329.  
  1330.         // 動詞の目的語になれなかった前置詞
  1331.         if((p->frPart & FR_PART_VERB)
  1332.         && p->which
  1333.         && (next->frPart & FR_PART_PREPOSIT)
  1334.         && (next->frPartChoice == FR_PART_OBJECT)) {
  1335.             currentTree->prtControl = PRT_CONTROL_DISABLE;
  1336.             isChanged = TRUE;
  1337.             break;
  1338.         }
  1339.     }
  1340. }
  1341.  
  1342. void
  1343. CheckIllegalCombine(TOKEN *start)
  1344. {
  1345.     TOKEN    *p;
  1346.  
  1347.     for(p = start; p; p = p->next) {
  1348.         if(IsObjectMatch(p, FR_PART_SENTENCE_ALL)    // この連結詞は、誤用だった(おてつき)
  1349.         &&   p->next
  1350.         &&  (p->next->frPart & FR_PART_COMBINE)
  1351.         && !(p->next->frPart & FR_PART_VERB)
  1352.         &&  (p->next->object1 == NULL || p->next->object2 == NULL)
  1353.         &&  p->next->next
  1354.         && IsObjectMatch(p->next->next, FR_PART_SENTENCE_ALL)) {
  1355.             currentTree->prtControl = PRT_CONTROL_DISABLE;
  1356.             return;
  1357.         }
  1358.     }
  1359. }
  1360.  
  1361. void
  1362. CheckIllegalCommaCombine(TOKEN *start)
  1363. {
  1364.     TOKEN    *p;
  1365.     for(p = start; p && p->next; p = p->next) {
  1366.         TOKEN    *next = p->next;
  1367.  
  1368.         if(!(next->frPart & FR_PART_NOUN))
  1369.             continue;
  1370.  
  1371.         if((p->frPart & FR_PART_PREPOSIT)
  1372.         && !(p->frPart & FR_PART_COMBINE)
  1373.         &&  p->which == NULL
  1374.         && MatchPrepositionObject(p, next)) {
  1375.             p = next;
  1376.             continue;
  1377.         }
  1378.         if((p->frPart & FR_PART_VERB)
  1379.         &&  p->which == NULL) {
  1380.             p = next;
  1381.             continue;
  1382.         }
  1383.  
  1384.         TOKEN    *combine = next->next;
  1385.         if( combine
  1386.         && !(combine->frPart & FR_PART_COMBINE)
  1387.         && IsObjectMatch(combine, FR_PART_COMBINE_NOUN, JP_PROP_NONE, NULL, ",")
  1388.         && combine->object1
  1389.         && combine->object2) {
  1390.             currentTree->prtControl = PRT_CONTROL_DISABLE;
  1391.             isChanged = TRUE;
  1392.             break;
  1393.         }
  1394.     }
  1395. }
  1396.  
  1397.  
  1398. void
  1399. ProcessInsertedComma(TOKEN *start)
  1400. {
  1401.     TOKEN    *prev = start;
  1402.     TOKEN    *p = prev->next;
  1403.  
  1404.     for(; p && p->next; prev = p, p = p->next) {
  1405.         TOKEN    *next = p->next;
  1406.  
  1407.         if(p->frPart != FR_PART_SPECIAL_COMMA)
  1408.             continue;
  1409.  
  1410.         // Tout ce que tu as observ{ en France<,> a bien chang{.
  1411.         if((prev->frPart & FR_PART_NOUN)
  1412.         && CountTokens(prev->child) >= 4
  1413.         && (next->frPart & FR_PART_VERB)) {
  1414.             prev->punctuation = FR_PUNCT_COMMA;
  1415.             DisconnectTOKEN(start, p);
  1416.             return;
  1417.         }
  1418.         if(IsObjectMatch(prev, FR_PART_VERB_UNCLEAR)
  1419.         && prev->punctuation == FR_PUNCT_COMMA) {
  1420.             // Donnez<, Monsieur>, le stylo @ moi.
  1421.             DisconnectTOKEN(start, p);
  1422.             return;
  1423.         }
  1424.     }
  1425. }
  1426.  
  1427. //
  1428. // 親がいないTokenをチェック
  1429. //
  1430. void
  1431. MarkRootTokens(TOKEN *start)
  1432. {
  1433.     TOKEN *p;
  1434.  
  1435.     for(p = start; p; p = p->next) {
  1436.         p->jpEmphasis |= JP_EMPHASIS_ROOT;
  1437.     }
  1438. }
  1439.  
  1440. //
  1441. // 比較対象がない<Aussi>をチェック
  1442. //    eg) D'autres sont <aussi> contents.
  1443. //    他の人は<null><くらい>幸せだ -> 他の人<も>幸せだ
  1444. //
  1445. void
  1446. CheckNoChildAussi(TOKEN *start)
  1447. {
  1448.     TOKEN    *p;
  1449.     TOKEN    *lastSentence = NULL;
  1450.  
  1451.     for(p = start; p; p = p->next) {
  1452.         if(IsObjectMatch(p, FR_PART_SENTENCE_NORMAL))
  1453.             lastSentence = p;
  1454.     }
  1455.     if(lastSentence == NULL)    return;
  1456.  
  1457.     TOKEN *compWord =IsWordOwner(lastSentence, FR_ATTRIB_AUSSI);
  1458.     if(compWord == NULL)    return;
  1459.  
  1460.     // すでに、<de>(~の中で)を持っている。
  1461.     if(SearchToken(FR_PART_CONJUNCTION_THAN, compWord->child))
  1462.         return;
  1463.  
  1464.     if(lastSentence->subject) {
  1465.         compWord->frAttrib = (FR_ATTRIB)(compWord->frAttrib & ~FR_ATTRIB_AUSSI);
  1466.         lastSentence->subject->jpEmphasis |= JP_EMPHASIS_MO;
  1467.     }
  1468. }
  1469.  
  1470.  
  1471. //
  1472. // FR_PART_SENTENCEに掛かっている副詞をFR_PART_VERB ->childに移す
  1473. //
  1474. void
  1475. MoveSentenceAdverbToVerb(TOKEN *start)
  1476. {
  1477.     TOKEN    *p, *q;
  1478.  
  1479.     for(p = start; p; p = p->next) {
  1480.         if(p->child)    MoveSentenceAdverbToVerb(p->child);
  1481.         if(p->object1)    MoveSentenceAdverbToVerb(p->object1);
  1482.         if(p->object2)    MoveSentenceAdverbToVerb(p->object2);
  1483.  
  1484.         if(IsObjectMatch(p, FR_PART_SENTENCE_NORMAL)) {
  1485.             for(q = p->child; q; q = q->next) {
  1486.                 if(IsObjectMatch(q, FR_PART_PREPOSIT_ALL)
  1487.                 || IsObjectMatch(q, FR_PART_ADVERB_ALL)) {
  1488.                     DisconnectChildToken(p, q);
  1489.                     AddChildTOKEN(p->object2, q);
  1490.                 }
  1491.             }
  1492.         }
  1493.     }
  1494. }
  1495.